package com.examsystem.listener;
import com.examsystem.util.RedisUtil;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;


import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * @author fire'ge
 */
@Component
@ServerEndpoint("/webSocket/{userId}")
public class WebSocketListener {
    //与某个客户端的连接会话，需要通过它来给客户端发送数据

    //concurrent包的线程安全Set，用来存放每个客户端对应的MyWebSocket对象。
    //虽然@Component默认是单例模式的，但springboot还是会为每个websocket连接初始化一个bean，所以可以用一个静态set保存起来。
    //  注：底下WebSocket是当前类名4


    private Session session ;
    private String userId ;
    private RedisUtil redisUtil ;
    private static final CopyOnWriteArraySet<WebSocketListener> WEB_SOCKETS = new CopyOnWriteArraySet<>();
    //获取容器管理上下文

    private static ApplicationContext applicationContext;

    public static void setApplicationContext(ApplicationContext applicationContext) {
        WebSocketListener.applicationContext = applicationContext;
    }

    // 用来存在线连接数

    private static final Map<String, Session> SESSION_POOL = new HashMap<>();



    /**
     * 链接成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam(value = "userId") String userId) {
        try {
            redisUtil = applicationContext.getBean(RedisUtil.class);
            this.session = session;
            this.userId = userId;
            WEB_SOCKETS.add(this);
            SESSION_POOL.put(userId, session);
            System.out.println("onOpen is running");
            System.out.println(session);
            try {
                    session.getAsyncRemote().sendText("hello!!!");
            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 链接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        try {
            redisUtil.del("login:user"+userId);
            WEB_SOCKETS.remove(this);
            SESSION_POOL.remove(userId);
            System.out.println("onClose is running");

        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 发送错误时的处理
     *
     */
    @OnError
    public void onError(Throwable error) {
        WEB_SOCKETS.remove(this);
        SESSION_POOL.remove(userId);
        System.out.println("onError is running");
        redisUtil.del("login:user"+userId);
        error.printStackTrace();
        throw new RuntimeException(error.getMessage());
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (!(o instanceof WebSocketListener)) {
            return false;
        }

        WebSocketListener that = (WebSocketListener) o;

        if (!Objects.equals(session, that.session)) {
            return false;
        }
        if (!Objects.equals(userId, that.userId)) {
            return false;
        }
        return Objects.equals(redisUtil, that.redisUtil);
    }

    @Override
    public int hashCode() {
        int result = session != null ? session.hashCode() : 0;
        result = 31 * result + (userId != null ? userId.hashCode() : 0);
        result = 31 * result + (redisUtil != null ? redisUtil.hashCode() : 0);
        return result;
    }
}
